import grails.test.ControllerUnitTestCase
import groovy.mock.interceptor.MockFor

/**
 * Created by IntelliJ IDEA.
 * User: corcutt
 * Date: Apr 29, 2009
 * Time: 9:15:14 PM
 * To change this template use File | Settings | File Templates.
 */

class VolunteerControllerTests extends ControllerUnitTestCase {

  void testLogin_success() {
    setUpSession()
    controller.login()
    assertEquals('redirect controller', "event", redirectArgs.controller)
    assertEquals('redirect action', "futureEvents", redirectArgs.action)
  }

  void testLogin_failure() {
    controller.login()
    assertEquals ('render view', "login", renderArgs.view)
  }

  void testHandleLogin_invalidVolunteer() {
    def expectedVolunteer = createVolunteer()
    mockDomain(Volunteer, [expectedVolunteer])
    controller.params.email = "someothervalue@someplace.com"
    controller.handleLogin()
    assertEquals('flash error',
            "Invalid login",
            mockFlash.error)
    assertEquals ('render view', "login", renderArgs.view)
    assertNull mockSession.volunteer
  }

  void testHandleLogin_badLogin() {
    def expectedVolunteer = createVolunteer()
    mockDomain(Volunteer, [expectedVolunteer])
    controller.params.email = "bugsbunny@warnerbros.com"
    controller.params.password = "badpwd"
    controller.handleLogin()
    assertEquals('flash error',
            "Invalid login",
            mockFlash.error)
    assertEquals ('render view', "login", renderArgs.view)
    assertNull mockSession.volunteer
  }

  void testHandleLogin_success() {
    def expectedVolunteer = createVolunteer()
    mockDomain(Volunteer, [expectedVolunteer])
    controller.params.email = "bugsbunny@warnerbros.com"
    controller.params.password = "bb"
    controller.handleLogin()
    assertEquals('redirect controller', "event", redirectArgs.controller)
    assertEquals('redirect action', "futureEvents", redirectArgs.action)
    assertEquals (expectedVolunteer, mockSession.volunteer)
  }

  void testLogout() {
    setUpSession()
    assertNotNull mockSession.volunteer
    controller.logout()
    assertNull mockSession.volunteer
    assertEquals('redirect action', "login", redirectArgs.action)
  }

  void testList() {
    List expectedVolunteerList = []
    20.times {i -> expectedVolunteerList << new Volunteer() }
//    expectedVolunteerList = createVolunteerList()
    mockDomain(Volunteer, [expectedVolunteerList])
    Map model = controller.list()
    assertNotNull('list should be present in model', model.volunteerInstanceList)
    assertEquals('expected list is returned', expectedVolunteerList, model.volunteerInstanceList[0])
  }

  void testShow_invalidVolunteer() {
    def expectedVolunteer = createVolunteer()
    mockDomain(Volunteer, [expectedVolunteer])
    controller.params.id = 999
    controller.show()
    assertEquals('flash error',
            "Volunteer not found",
            mockFlash.error)
    assertEquals('redirect action',
            controller.list, redirectArgs.action)
  }

  void testShow_validVolunteer() {
    def expectedVolunteer = createVolunteer()
    mockDomain(Volunteer, [expectedVolunteer])
    controller.params.id = 1
    Map model = controller.show()
    assertEquals(expectedVolunteer, model.volunteerInstance)

  }

  void testDelete_notVolunteer() {
    setUpSession()
    controller.params.id = 999
    controller.delete()
    assertEquals('flash message',
           "You can only delete yourself",
            mockFlash.message)
    assertEquals('redirect action',
            controller.list, redirectArgs.action)
  }

  void testDelete_volunteerNotFound() {
    setUpSession()
    def mockVolunteer = new Volunteer()
    mockVolunteer.id = 99
    mockDomain(Volunteer, [mockVolunteer])
    controller.params.id = '1'
    controller.delete()
    assertNoSuchVolunteer()
  }

  void testDelete_success() {
    setUpSession()
    mockDomain(Volunteer, [mockSession.volunteer])
    controller.params.id = '1'
    controller.delete()
    assertEquals('flash message',
           "Volunteer ${controller.params.id} deleted",
            mockFlash.message)
    assertEquals('redirect action',
            controller.list, redirectArgs.action)
  }

  void testEdit_volunteerNotFound() {
    setUpSession()
    def mockVolunteer = new Volunteer()
    mockVolunteer.id = 99
    mockDomain(Volunteer, [mockVolunteer])
    controller.params.id = '1'
    controller.edit()
    assertNoSuchVolunteer()
  }

  void testEdit_success() {
    setUpSession()
    mockDomain(Volunteer, [mockSession.volunteer])
    controller.params.id = '1'
    Map model = controller.edit()
    assertEquals(mockSession.volunteer, model.volunteerInstance)
  }

  void testUpdate_notVolunteer() {
    setUpSession()
    controller.params.id = 999
    controller.update()
    assertEquals('flash message',
           "You can only update yourself",
            mockFlash.message)
    assertEquals('redirect action',
            controller.list, redirectArgs.action)
  }

  void testUpdate_volunteerNotFound() {
    setUpSession()
    def mockVolunteer = new Volunteer()
    mockVolunteer.id = 99
    mockDomain(Volunteer, [mockVolunteer])
    controller.params.id = '1'
    controller.update()
    assertEquals('flash message',
            "Volunteer not found",
            mockFlash.message)
    assertEquals('redirect action',
            controller.edit, redirectArgs.action)
  }

  void testUpdate_success() {
    setUpSession()
    mockDomain(Volunteer, [mockSession.volunteer])
    controller.params.id = '1'
    controller.update()
    assertEquals('flash message',
           "Volunteer updated",
            mockFlash.message)
    assertEquals('redirect action',
            controller.show, redirectArgs.action)

  }

  void testCreate() {
    mockDomain(Volunteer)
    Map model = controller.create()
    assertNotNull('volunteerInstance', model.volunteerInstance)
  }

  void testSave_failed() {
    mockDomain(Volunteer)
    // mock out save method for non-happy path
    Volunteer.metaClass.save = {-> return false}

    controller.save()

    assertEquals('render view', 'create', renderArgs.view)
    assertNotNull('volunteerInstance', renderArgs.model.volunteerInstance)

  }

  // has to be integration test due to grailsAttributes
//  void testSave_success() {
//  }

  private def assertNoSuchVolunteer() {
    assertEquals('flash message',
            "Volunteer not found",
            mockFlash.message)
    assertEquals('redirect action',
            controller.list, redirectArgs.action)
  }

  private def setUpSession() {
    mockSession.volunteer = createVolunteer()
    mockSession.volunteer.id = 1
  }

  Volunteer createVolunteer() {
   return new Volunteer(firstName: 'Bugs', lastName: 'Bunny', email: 'bugsbunny@warnerbros.com', password: 'bb')
  }

  Volunteer[] createVolunteerList() {
    def v1 = new Volunteer(firstName: 'Bugs', lastName: 'Bunny', email: 'bugsbunny@warnerbros.com', password: 'bb')
    def v2 = new Volunteer(firstName: 'Elmer', lastName: 'Fudd', email: 'efudd@warnerbros.com', password: 'ef')
    def v3 = new Volunteer(firstName: 'Pepe', lastName: 'LePew', email: 'pepe@warnerbros.com', password: 'pp')
    return [v1, v2, v3]
  }

}
